import math
from typing import List

from common.params import SoftParams, CasingParams
from model.soft.soft_common import AxialForceResult, data_init


# 计算液体阻力------通用公式
def get_fluid_resistance(tao_p: float, rate: float, v:float, L: float)-> float:
    # 定义计算元
    factor_a: float = 2 * math.pi * tao_p * L * v
    # print("factor_a为：",factor_a)
    factor_b: float = math.pow(rate, 2) - 1
    # print("factor_b为：", factor_b)
    factor_c: float = (math.pow(rate, 2) + 1) * math.log(rate)
    # print("factor_c为：", factor_c)
    # 计算结果
    res: float = (factor_a * factor_b) / (factor_c - factor_b)
    return res


# 计算下放流体阻力---工具
def tool_push_fluid(params: SoftParams, cur: AxialForceResult) -> float:
    # 是否在套管范围内
    in_casing: bool = False
    # 获取套管信息列表
    casings: List[CasingParams] = params.casings
    for c_item in casings:
        # 处于套管范围内
        if (cur.depth >= c_item.start) and (cur.depth <= c_item.end):
            in_casing = True
            rate = params.get_instrument_rate(cur.depth)
            res: float = get_fluid_resistance(params.tao_p, rate, params.v_push, params.L1)
            return res
    # 不在套管范围内
    if in_casing == False:
        rate = params.get_instrument_rate(cur.depth)
        res: float = get_fluid_resistance(params.tao_p, rate, params.v_push, params.L1)
        return res


# 计算上提流体阻力----工具
def tool_pull_fluid(params: SoftParams, cur: AxialForceResult) -> float:
    # 是否在套管范围内
    in_casing: bool = False
    # 获取套管信息列表
    casings: List[CasingParams] = params.casings
    for c_item in casings:
        # 处于套管范围内
        if (cur.depth >= c_item.start) and (cur.depth <= c_item.end):
            in_casing = True
            rate: float = params.get_instrument_rate(cur.depth)
            res: float = get_fluid_resistance(params.tao_p, rate, params.v_pull, params.L1)
            return res
    # 不在套管范围内
    if in_casing == False:
        rate: float = params.get_instrument_rate(cur.depth)
        res: float = get_fluid_resistance(params.tao_p, rate, params.v_pull, params.L1)
        return res


# 请使用上边的通用计算函数
# 计算井下电缆的液体阻力 实际是分为三步
# 在一开套管位置是只计算d-L1的(如果没有一开套管就默认裸眼段是一开套管)
# 在二开是计算Lc1 和 d-L1-Lc1
# 从三开以后计算 Lc1、Lc2-Lc1、Lc(n-1)-Lc(n-2)和d-L1-Lc(n-1)
# 先判断套管列表的长度 如果套管长度为0 全部是裸眼段 则不在套管范围内 只计算d-L1
# 如果套管范围为1 实际计算一开的d-L1和Lc1 但是一开的实际值为d-L1，Lc1的放在裸眼段，再计算裸眼段的 d-L1-Lc1，对Lc1和d-L1-Lc1进行求和计算就是裸眼段的
# 如果套管范围为2 实际计算一开的d-L1和Lc1 但是一开的实际值为d-L1，Lc1放在二开和裸眼段，再计算二开的 d-L1-Lc1，对Lc1和d-L1-Lc1进行求和计算就是二开的，
# 裸眼的为Lc1+（Lc2-Lc1）+（d-L1-Lc2）


def cable_push_fluid(params: SoftParams, cur: AxialForceResult) -> float:
    # 是否在套管范围内
    in_casing: bool = False
    # 获取套管信息列表
    casings: List[CasingParams] = params.casings
    # 获取套管的长度
    num_casings = len(casings)
    # 设置一个空的数组 保存中间的计算值
    results = []
    for i, c_item in enumerate(casings):
        # 处于套管范围内
        if (cur.depth >= c_item.start) and (cur.depth <= c_item.end):
            results.append(cur.depth)
            in_casing = True
            if num_casings >= 1:
                # 如果只有一开套管 则只在套管范围内只计算 d_L1 并且比值为当前套管所处的比值
                if num_casings == 1:
                    rate: float = params.get_cable_rate(cur.depth)
                    # 一开套管内的流体阻力就是 d_Lc1
                    d_L1: float = get_fluid_resistance(params.tao_p, rate, params.v_push, cur.depth - params.L1)
                    res = d_L1
                    return res
                # 如果只有两个套管 需要在一开套管内计算d_L1 并且比值为一开套管所处的比值 此外二开套管的计算为：一开套管比值的Lc1+二开套管比值的d_L1_Lcn_1
                elif num_casings == 2:
                    # 先计算在一开套管内的值
                    if (cur.depth >= int(casings[0].start)) and (cur.depth <= int(casings[0].end)):
                        rate1: float = params.get_cable_rate(cur.depth)
                        d_L1: float = get_fluid_resistance(params.tao_p, rate1, params.v_push, cur.depth - params.L1)
                        res = d_L1
                        return res
                    # 计算二开套管范围内任意深度的流体阻力 由两部分组成
                    # 第一部分----一开比值的Lc1
                    rate2_1: float = params.get_cable_rate(casings[0].end)  # 此处的比值可以是一开套管的结束深度也可以用一开套管的任意深度
                    Lc1: float = get_fluid_resistance(params.tao_p, rate2_1, params.v_push, casings[0].end)
                    # 第二部分------二开比值的d_L1_Lcn_1
                    rate2_2: float = params.get_cable_rate(cur.depth)
                    d_L1_Lcn_1: float = get_fluid_resistance(params.tao_p, rate2_2, params.v_push, cur.depth - params.L1 - casings[0].end)
                    res = Lc1 + d_L1_Lcn_1
                    return res
                # 如果有两个以上的套管 需要在一开套管内计算d_L1 并且比值为一开套管所处的比值 此外二开套管的计算为：一开套管比值的Lc1+二开套管比值的d_L1_Lcn_1 三开及以上的需要循环拿到Lcn_Lcn_1
                elif num_casings > 2:
                    # 先计算在一开套管内的值
                    if (cur.depth >= casings[0].start) and (cur.depth <= casings[0].end):
                        rate1: float = params.get_cable_rate(cur.depth)
                        d_L1: float = get_fluid_resistance(params.tao_p, rate1, params.v_push, cur.depth - params.L1)
                        res = d_L1
                        return res
                    # 计算二开套管范围内任意深度的流体阻力 由两部分组成 并且是在二开深度范围内进行
                    elif (cur.depth >= casings[1].start) and (cur.depth <= casings[1].end):
                        # 第一部分----一开比值的Lc1
                        # 当前位置按说应该用一开的深度 为便于计算 固定当前的rate是一开的结束深度 而不是cur.depth(cur.depth指的是当前套管深度内的)
                        rate2_1: float = params.get_cable_rate(casings[0].end)
                        # 先计算一开套管末尾处的流体阻力
                        Lc1: float = get_fluid_resistance(params.tao_p, rate2_1, params.v_push, casings[0].end)
                        # 计算从二开开始的 二开内部深度的只需要d_L1_Lcn_1
                        rate2_2: float = params.get_cable_rate(cur.depth)
                        d_L1_Lcn_1: float = get_fluid_resistance(params.tao_p, rate2_2, params.v_push, cur.depth - params.L1 - casings[i - 1].end)
                        # 流体阻力的累积
                        res = Lc1 + d_L1_Lcn_1
                        return res
                    # 开始进行大于等于三个套管内部 该部分需要循环计算Lcn_Lcn_1
                    # 三开的时候计算一开套管比值的Lc1+二开套管比值的Lcn_Lcn_1+三开套管比值的d_L1_Lcn_1 简称Lc1+Lc2_Lc1+d_L1_Lc2
                    # 四开的时候计算一开套管比值的Lc1+二开套管比值的Lcn_Lcn_1+三开套管比值的Lcn_Lcn_1+四开套管比值的d_L1_Lcn_1 简称Lc1+Lc2_Lc1+Lc3_Lc2+d_L1_Lc3
                    elif cur.depth > casings[1].end:
                        # 第一部分 - ---一开比值的Lc1
                        # 当前位置按说应该用一开的深度 为便于计算 固定当前的rate是一开的结束深度 而不是cur.depth(cur.depth指的是当前套管深度内的)
                        rate1: float = params.get_cable_rate(casings[0].end)
                        # 先计算一开套管末尾处的流体阻力
                        Lc1: float = get_fluid_resistance(params.tao_p, rate1, params.v_push, casings[0].end)
                        # 第二部分 -----二开到n-1开比值的Lcn_Lcn_1
                        # 只有三开的时候开始加上Lcn_Lcn_1 后续循环处理Lcn_Lcn_1 并在最终结果上加上
                        Lcn_Lcn_1: float = 0
                        # 由于最小的Lci_Lci_1是三开段的Lc2_Lc1 所以从2开始 以num_casings套管长度结束 并且比值是Lc2段的比值
                        # 即比值用casings[i_item - 1].end 区间段相减是casings[i_item - 1].end - casings[i_item - 2].end
                        for i_item in range(2, num_casings + 1):
                            # 当前套管的速率
                            current_rate: float = params.get_cable_rate(casings[i_item - 1].end)
                            # 计算当前套管和前一个套管之间的流体阻力
                            Lci_Lci_1: float = get_fluid_resistance(params.tao_p, current_rate, params.v_push, casings[i_item - 1].end - casings[i_item - 2].end)
                            # 多个累加
                            Lcn_Lcn_1 += Lci_Lci_1
                        # 第三部分 -----计算从三开开始的d_L1_Lcn_1
                        rate3: float = params.get_cable_rate(cur.depth)
                        d_L1_Lcn_1: float = get_fluid_resistance(params.tao_p, rate3, params.v_push, cur.depth - params.L1 - casings[num_casings - 1].end)
                        # 流体阻力的累积
                        res = Lc1 + d_L1_Lcn_1
                        res += Lcn_Lcn_1
                        return res

    # 不在套管范围内
    if in_casing == False:
        results.append(cur.depth)
        # 如果没有套管存在 就默认该井的裸眼段计算过程为正常一开套管的计算过程 只不过是比值用裸眼段的计算
        if num_casings == 0:
            rate: float = params.get_cable_rate(cur.depth)
            d_Lc1: float = get_fluid_resistance(params.tao_p, rate, params.v_push, cur.depth - params.L1)
            res = d_Lc1
            return res
        # 如果存在一开套管 则该部分就相当于二开套管的计算 只不过第二部用的比值为裸眼段的比值
        elif num_casings == 1:
            # 计算从一开套管末尾到当前位置的流体阻力
            rate1: float = params.get_cable_rate(casings[0].end)
            Lc1: float = get_fluid_resistance(params.tao_p, rate1, params.v_push, casings[0].end)
            # 计算从“二开”开始的裸眼段计算 比值用裸眼段的
            rate2: float = params.get_cable_rate(cur.depth)
            d_L1_Lcn_1: float = get_fluid_resistance(params.tao_p, rate2, params.v_push, cur.depth - params.L1 - casings[0].end)
            res = Lc1 + d_L1_Lcn_1
            return res
        # 如果有两开及以上套管 该部分就是要计算三部分
        elif num_casings >= 2:
            # 第一步-----计算从一开套管末尾到当前位置的流体阻力
            rate1: float = params.get_cable_rate(casings[0].end)  # 一开套管结束深度
            Lc1: float = get_fluid_resistance(params.tao_p, rate1, params.v_push, casings[0].end)
            # 第二步-----循环计算n开和n-1开之间的流体阻力 用比值为v开套管的结束深度参与计算
            # 循环处理从二开开始的套管
            Lcn_Lcn_1: float = 0
            for i in range(2, num_casings + 1):
                # 当前套管的速率
                current_rate: float = params.get_cable_rate(casings[i - 1].end)
                # 计算当前套管和前一个套管之间的流体阻力
                Lci_Lci_1: float = get_fluid_resistance(params.tao_p, current_rate, params.v_push, casings[i - 1].end - casings[i - 2].end)
                Lcn_Lcn_1 += Lci_Lci_1
            # 第三步-----计算裸眼段比值的相关内容 计算从最后一个套管末尾到当前位置的流体阻力d_L1_Lcn_1
            rate_oh: float = params.get_cable_rate(cur.depth)
            d_L1_Lcn_1: float = get_fluid_resistance(params.tao_p, rate_oh, params.v_push, cur.depth - params.L1 - casings[num_casings - 1].end)
            # 裸眼段的总的流体阻力为三部分相加
            res = Lc1 + Lcn_Lcn_1 + d_L1_Lcn_1
            return res


def cable_pull_fluid(params: SoftParams, cur: AxialForceResult) -> float:
    # 是否在套管范围内
    in_casing: bool = False
    # 获取套管信息列表
    casings: List[CasingParams] = params.casings
    # 获取套管的长度
    num_casings = len(casings)
    # 设置一个空的数组 保存中间的计算值
    results = []
    for i, c_item in enumerate(casings):
        # 处于套管范围内
        if (cur.depth >= c_item.start) and (cur.depth <= c_item.end):
            results.append(cur.depth)
            in_casing = True
            if num_casings >= 1:
                # 如果只有一开套管 则只在套管范围内只计算 d_L1 并且比值为当前套管所处的比值
                if num_casings == 1:
                    rate: float = params.get_cable_rate(cur.depth)
                    # 一开套管内的流体阻力就是 d_Lc1
                    d_L1: float = get_fluid_resistance(params.tao_p, rate, params.v_pull, cur.depth - params.L1)
                    res = d_L1
                    return res
                # 如果只有两个套管 需要在一开套管内计算d_L1 并且比值为一开套管所处的比值 此外二开套管的计算为：一开套管比值的Lc1+二开套管比值的d_L1_Lcn_1
                elif num_casings == 2:
                    # 先计算在一开套管内的值
                    if (cur.depth >= int(casings[0].start)) and (cur.depth <= int(casings[0].end)):
                        rate1: float = params.get_cable_rate(cur.depth)
                        d_L1: float = get_fluid_resistance(params.tao_p, rate1, params.v_pull, cur.depth - params.L1)
                        res = d_L1
                        return res
                    # 计算二开套管范围内任意深度的流体阻力 由两部分组成
                    # 第一部分----一开比值的Lc1
                    rate2_1: float = params.get_cable_rate(casings[0].end)  # 此处的比值可以是一开套管的结束深度也可以用一开套管的任意深度
                    Lc1: float = get_fluid_resistance(params.tao_p, rate2_1, params.v_pull, casings[0].end)
                    # 第二部分------二开比值的d_L1_Lcn_1
                    rate2_2: float = params.get_cable_rate(cur.depth)
                    d_L1_Lcn_1: float = get_fluid_resistance(params.tao_p, rate2_2, params.v_pull, cur.depth - params.L1 - casings[0].end)
                    res = Lc1 + d_L1_Lcn_1
                    return res
                # 如果有两个以上的套管 需要在一开套管内计算d_L1 并且比值为一开套管所处的比值 此外二开套管的计算为：一开套管比值的Lc1+二开套管比值的d_L1_Lcn_1 三开及以上的需要循环拿到Lcn_Lcn_1
                elif num_casings > 2:
                    # 先计算在一开套管内的值
                    if (cur.depth >= casings[0].start) and (cur.depth <= casings[0].end):
                        rate1: float = params.get_cable_rate(cur.depth)
                        d_L1: float = get_fluid_resistance(params.tao_p, rate1, params.v_pull, cur.depth - params.L1)
                        res = d_L1
                        return res
                    # 计算二开套管范围内任意深度的流体阻力 由两部分组成 并且是在二开深度范围内进行
                    elif (cur.depth >= casings[1].start) and (cur.depth <= casings[1].end):
                        # 第一部分----一开比值的Lc1
                        # 当前位置按说应该用一开的深度 为便于计算 固定当前的rate是一开的结束深度 而不是cur.depth(cur.depth指的是当前套管深度内的)
                        rate2_1: float = params.get_cable_rate(casings[0].end)
                        # 先计算一开套管末尾处的流体阻力
                        Lc1: float = get_fluid_resistance(params.tao_p, rate2_1, params.v_pull, casings[0].end)
                        # 计算从二开开始的 二开内部深度的只需要d_L1_Lcn_1
                        rate2_2: float = params.get_cable_rate(cur.depth)
                        d_L1_Lcn_1: float = get_fluid_resistance(params.tao_p, rate2_2, params.v_pull, cur.depth - params.L1 - casings[i - 1].end)
                        # 流体阻力的累积
                        res = Lc1 + d_L1_Lcn_1
                        return res
                    # 开始进行大于等于三个套管内部 该部分需要循环计算Lcn_Lcn_1
                    # 三开的时候计算一开套管比值的Lc1+二开套管比值的Lcn_Lcn_1+三开套管比值的d_L1_Lcn_1 简称Lc1+Lc2_Lc1+d_L1_Lc2
                    # 四开的时候计算一开套管比值的Lc1+二开套管比值的Lcn_Lcn_1+三开套管比值的Lcn_Lcn_1+四开套管比值的d_L1_Lcn_1 简称Lc1+Lc2_Lc1+Lc3_Lc2+d_L1_Lc3
                    elif cur.depth > casings[1].end:
                        # 第一部分 - ---一开比值的Lc1
                        # 当前位置按说应该用一开的深度 为便于计算 固定当前的rate是一开的结束深度 而不是cur.depth(cur.depth指的是当前套管深度内的)
                        rate1: float = params.get_cable_rate(casings[0].end)
                        # 先计算一开套管末尾处的流体阻力
                        Lc1: float = get_fluid_resistance(params.tao_p, rate1, params.v_pull, casings[0].end)
                        # 第二部分 -----二开到n-1开比值的Lcn_Lcn_1
                        # 只有三开的时候开始加上Lcn_Lcn_1 后续循环处理Lcn_Lcn_1 并在最终结果上加上
                        Lcn_Lcn_1: float = 0
                        # 由于最小的Lci_Lci_1是三开段的Lc2_Lc1 所以从2开始 以num_casings套管长度结束 并且比值是Lc2段的比值
                        # 即比值用casings[i_item - 1].end 区间段相减是casings[i_item - 1].end - casings[i_item - 2].end
                        for i_item in range(2, num_casings + 1):
                            # 当前套管的速率
                            current_rate: float = params.get_cable_rate(casings[i_item - 1].end)
                            # 计算当前套管和前一个套管之间的流体阻力
                            Lci_Lci_1: float = get_fluid_resistance(params.tao_p, current_rate, params.v_pull, casings[i_item - 1].end - casings[i_item - 2].end)
                            # 多个累加
                            Lcn_Lcn_1 += Lci_Lci_1
                        # 第三部分 -----计算从三开开始的d_L1_Lcn_1
                        rate3: float = params.get_cable_rate(cur.depth)
                        d_L1_Lcn_1: float = get_fluid_resistance(params.tao_p, rate3, params.v_pull, cur.depth - params.L1 - casings[num_casings - 1].end)
                        # 流体阻力的累积
                        res = Lc1 + d_L1_Lcn_1
                        res += Lcn_Lcn_1
                        return res

    # 不在套管范围内
    if in_casing == False:
        results.append(cur.depth)
        # 如果没有套管存在 就默认该井的裸眼段计算过程为正常一开套管的计算过程 只不过是比值用裸眼段的计算
        if num_casings == 0:
            rate: float = params.get_cable_rate(cur.depth)
            d_Lc1: float = get_fluid_resistance(params.tao_p, rate, params.v_pull, cur.depth - params.L1)
            res = d_Lc1
            return res
        # 如果存在一开套管 则该部分就相当于二开套管的计算 只不过第二部用的比值为裸眼段的比值
        elif num_casings == 1:
            # 计算从一开套管末尾到当前位置的流体阻力
            rate1: float = params.get_cable_rate(casings[0].end)
            Lc1: float = get_fluid_resistance(params.tao_p, rate1, params.v_pull, casings[0].end)
            # 计算从“二开”开始的裸眼段计算 比值用裸眼段的
            rate2: float = params.get_cable_rate(cur.depth)
            d_L1_Lcn_1: float = get_fluid_resistance(params.tao_p, rate2, params.v_pull, cur.depth - params.L1 - casings[0].end)
            res = Lc1 + d_L1_Lcn_1
            return res
        # 如果有两开及以上套管 该部分就是要计算三部分
        elif num_casings >= 2:
            # 第一步-----计算从一开套管末尾到当前位置的流体阻力
            rate1: float = params.get_cable_rate(casings[0].end)  # 一开套管结束深度
            Lc1: float = get_fluid_resistance(params.tao_p, rate1, params.v_pull, casings[0].end)
            # 第二步-----循环计算n开和n-1开之间的流体阻力 用比值为v开套管的结束深度参与计算
            # 循环处理从二开开始的套管
            Lcn_Lcn_1: float = 0
            for i in range(2, num_casings + 1):
                # 当前套管的速率
                current_rate: float = params.get_cable_rate(casings[i - 1].end)
                # 计算当前套管和前一个套管之间的流体阻力
                Lci_Lci_1: float = get_fluid_resistance(params.tao_p, current_rate, params.v_pull, casings[i - 1].end - casings[i - 2].end)
                Lcn_Lcn_1 += Lci_Lci_1
            # 第三步-----计算裸眼段比值的相关内容 计算从最后一个套管末尾到当前位置的流体阻力d_L1_Lcn_1
            rate_oh: float = params.get_cable_rate(cur.depth)
            d_L1_Lcn_1: float = get_fluid_resistance(params.tao_p, rate_oh, params.v_pull, cur.depth - params.L1 - casings[num_casings - 1].end)
            # 裸眼段的总的流体阻力为三部分相加
            res = Lc1 + Lcn_Lcn_1 + d_L1_Lcn_1
            return res


if __name__ == '__main__':
    tao_p: float = 0.06
    rate_instrument: float = 0.135 / 0.09
    rate_instrument_2: float = 0.128 / 0.09

    rate_oh_instrument: float = 0.215 / 0.09
    rate_cable: float = 0.135 / 0.0118
    rate_oh_cable: float = 0.215 / 0.0118
    v: float = 1
    L1: float = 15
    L2: float = 2100
    print("-----------井下工具所受液体阻力--15m-----------------")
    result_instrument = get_fluid_resistance(tao_p, rate_instrument, v, L1)
    print("result_instrument为：",result_instrument)
    result_instrument_2 = get_fluid_resistance(tao_p, rate_instrument_2, v, L1)
    print("result_instrument_2为：", result_instrument_2)
    result_oh_instrument = get_fluid_resistance(tao_p, rate_oh_instrument, v, L1)
    print("result_oh_instrument为：",result_oh_instrument)
    # print("-----------井下电缆所受液体阻力--16m-----------------")
    # result_cable = get_fluid_resistance(tao_p, rate_cable, v, 1)
    # print("result_cable为：", result_cable)
    # result_oh_cable = get_fluid_resistance(tao_p, rate_oh_cable, v, L2 - L1 - 265)
    # print("result_oh_cable为：", result_oh_cable)
    # add_result = result_cable + result_oh_cable
    # print("两者之和为：", add_result)
